package cn.iocoder.yudao.module.project.service.kismaterielexwarehouse;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.project.config.projectDefine;
import cn.iocoder.yudao.module.project.controller.admin.kismaterielexwarehouserecycle.vo.KisMaterielExWarehouseRecyclePageReqVO;
import cn.iocoder.yudao.module.project.controller.admin.order.vo.OrderFlexNumVO;
import cn.iocoder.yudao.module.project.controller.admin.order.vo.PreparationVO;
import cn.iocoder.yudao.module.project.dal.dataobject.dispatchlist.DispatchListDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalcode.InternalCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalworkstationplan.InternalWorkstationPlanDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kisbatchcode.KisBatchCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehousehistory.KisMaterielExWarehouseHistoryDO;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehouserecycle.KisMaterielExWarehouseRecycleDO;
import cn.iocoder.yudao.module.project.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.workstation.WorkstationDO;
import cn.iocoder.yudao.module.project.dal.mysql.dispatchlist.DispatchListMapper;
import cn.iocoder.yudao.module.project.dal.mysql.internalworkstationplan.InternalWorkstationPlanMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kisbatchcode.KisBatchCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehousehistory.KisMaterielExWarehouseHistoryMapper;
import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehouserecycle.KisMaterielExWarehouseRecycleMapper;
import cn.iocoder.yudao.module.project.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.project.dal.mysql.orderdetail.OrderDetailMapper;
import cn.iocoder.yudao.module.project.dal.mysql.workstation.WorkstationMapper;
import cn.iocoder.yudao.module.project.service.internalcode.InternalCodeService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.project.controller.admin.kismaterielexwarehouse.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.kismaterielexwarehouse.KisMaterielExWarehouseDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.project.dal.mysql.kismaterielexwarehouse.KisMaterielExWarehouseMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.project.config.projectDefine.HTTP_STATUS.ERROR_STATUS;
import static cn.iocoder.yudao.module.project.config.projectDefine.MATERIAL_STATUS.*;
import static cn.iocoder.yudao.module.project.config.projectDefine.SERIAL_STR.SERIAL_NUMBER_INIT;
import static cn.iocoder.yudao.module.project.config.projectDefine.SUBMIT_STATUS.SUBMIT_STATUS_0;
import static cn.iocoder.yudao.module.project.config.projectDefine.SUBMIT_STATUS.SUBMIT_STATUS_1;
import static cn.iocoder.yudao.module.project.enums.ErrorCodeConstants.*;

/**
 * 物料出库单 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class KisMaterielExWarehouseServiceImpl implements KisMaterielExWarehouseService {

    @Resource
    private KisMaterielExWarehouseMapper kisMaterielExWarehouseMapper;

    @Resource
    private KisBatchCodeMapper kisBatchCodeMapper;

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private KisMaterielExWarehouseHistoryMapper kisMaterielExWarehouseHistoryMapper;

    @Resource
    private KisMaterielExWarehouseRecycleMapper kisMaterielExWarehouseRecycleMapper;

    @Resource
    private DispatchListMapper dispatchListMapper;

    @Resource
    private InternalCodeService internalCodeService;

    @Resource
    private WorkstationMapper workstationMapper;

    @Resource
    private InternalWorkstationPlanMapper internalWorkstationPlanMapper;

    @Override
    public String createKisMaterielExWarehouse(KisMaterielExWarehouseSaveReqVO createReqVO) {
        // 插入
        KisMaterielExWarehouseDO kisMaterielExWarehouse = BeanUtils.toBean(createReqVO, KisMaterielExWarehouseDO.class);
        kisMaterielExWarehouseMapper.insert(kisMaterielExWarehouse);
        // 返回
        return kisMaterielExWarehouse.getId();
    }

    @Override
    public void updateKisMaterielExWarehouse(KisMaterielExWarehouseSaveReqVO updateReqVO) {
        // 校验存在
        validateKisMaterielExWarehouseExists(updateReqVO.getId());
        // 更新
        KisMaterielExWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, KisMaterielExWarehouseDO.class);
        kisMaterielExWarehouseMapper.updateById(updateObj);
    }

    @Override
    public void deleteKisMaterielExWarehouse(String id) {
        // 校验存在
        validateKisMaterielExWarehouseExists(id);
        // 删除
        kisMaterielExWarehouseMapper.deleteById(id);
    }

    private void validateKisMaterielExWarehouseExists(String id) {
        if (kisMaterielExWarehouseMapper.selectById(id) == null) {
            throw exception(KIS_MATERIEL_EX_WAREHOUSE_NOT_EXISTS);
        }
    }

    @Override
    public KisMaterielExWarehouseDO getKisMaterielExWarehouse(String id) {
        return kisMaterielExWarehouseMapper.selectById(id);
    }

    @Override
    public PageResult<KisMaterielExWarehouseDO> getKisMaterielExWarehousePage(KisMaterielExWarehousePageReqVO pageReqVO) {
        return kisMaterielExWarehouseMapper.selectPage(pageReqVO);
    }


    @Override
    public List<KisMaterielExWarehouseDO> selectSavedList(Map<String, Object> params) {
        List<KisMaterielExWarehouseDO> list = kisMaterielExWarehouseMapper.selectSavedList(params);
        return list;
    }

    @Override
    public void insertRecord(List<KisMaterielExWarehouseDO> insertList) {
        // 插入
        if (null != insertList && insertList.size() > 0) {
            insertList = insertList.stream().distinct().collect(Collectors.toList());
            kisMaterielExWarehouseMapper.insertList(insertList);
        }
    }

    @Override
    public void updateRecord(List<KisMaterielExWarehouseDO> updateList) {
        // 更新
        if (null != updateList && updateList.size() > 0) {
            LocalDateTime today = LocalDateTimeUtil.now();
            for (KisMaterielExWarehouseDO data : updateList) {
                data.setUpdateTime(today);
            }
            kisMaterielExWarehouseMapper.updateList(updateList);
        }
    }

    @Override
    public String bondCartonCode(KisMaterielExWarehouseSaveReqVO createReqVO) {
        String orderCode = createReqVO.getOrderCode();
        String type = createReqVO.getType();
        String cartonCode = createReqVO.getCartonCode();
        String code = createReqVO.getCode();
        String operator = createReqVO.getOperator();

        KisBatchCodeDO kisBatchCodeDO = kisBatchCodeMapper.selectById(cartonCode);
        if (null == kisBatchCodeDO) {
            throw new ServiceException(ERROR_STATUS, "箱码不存在,请重新扫码");
        }

        // 根据生产订单和型号去查该物料出库单是否绑定了箱码,如果没绑定则绑定
        QueryWrapper<KisMaterielExWarehouseDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", orderCode);
        queryWrapper.eq("type", type);
        queryWrapper.eq("code", code);
        String id = createReqVO.getId();
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            // LocalDate localDate = LocalDate.now();
            // LocalDateTime updateDate = localDate.atTime(0, 0, 0);
            LocalDateTime updateTime = LocalDateTime.now();
            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                kisMaterielExWarehouseDO.setCartonCode(cartonCode);
                kisMaterielExWarehouseDO.setOperator(operator);
                kisMaterielExWarehouseDO.setUpdateTime(updateTime);
                kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
            }
        }
        if (CollectionUtil.isEmpty(kisMaterielExWarehouseDOS)) {
            KisMaterielExWarehouseDO kisMaterielExWarehouseDO = BeanUtils.toBean(createReqVO, KisMaterielExWarehouseDO.class);
            kisMaterielExWarehouseDO.setCartonCode(cartonCode);
            // kisMaterielExWarehouseDO.setId(UuidUtil.getUuid());
            kisMaterielExWarehouseDO.setId(orderCode + "_" + type + "_" + code);
            kisMaterielExWarehouseDO.setOperator(operator);
            kisMaterielExWarehouseMapper.insert(kisMaterielExWarehouseDO);
            return kisMaterielExWarehouseDO.getId();
        }
        return id;
    }

    @Override
    public String bondMultiCartonCode(KisMaterielExWarehouseSaveReqVO createReqVO) {
        String orderCode = createReqVO.getOrderCode();
        String cartonCode = createReqVO.getCartonCode();
        String operator = createReqVO.getOperator();

        KisBatchCodeDO kisBatchCodeDO = kisBatchCodeMapper.selectById(cartonCode);
        if (null == kisBatchCodeDO) {
            throw new ServiceException(ERROR_STATUS, "箱码不存在,请重新扫码");
        }

        String[] cartonCodeArr = cartonCode.split("_");
        if (cartonCodeArr.length != 3) {
            throw new ServiceException(ERROR_STATUS, "箱码格式错误,请重新扫码");
        }
        String code = cartonCodeArr[0];

        // 根据生产订单和型号去查该物料出库单是否绑定了箱码,如果没绑定则绑定
        QueryWrapper<KisMaterielExWarehouseDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", orderCode);
        queryWrapper.eq("code", code);
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            LocalDateTime updateTime = LocalDateTime.now();
            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                String existCartonCode = kisMaterielExWarehouseDO.getCartonCode();
                if (StringUtils.isBlank(existCartonCode)) {
                    existCartonCode = "";
                }
                // 对数据库的箱码进行分割,如果匹配到前端传入的箱码,则不用修改.如果未匹配到前端传入的箱码,则将前端传入的箱码拼接到数据库的箱码
                String[] existCartonCodeArr = existCartonCode.split(",");
                if (StringUtils.isNotBlank(existCartonCode) && existCartonCodeArr.length > 0 && !Arrays.asList(existCartonCodeArr).contains(cartonCode)) {
                    List<String> cartonCodeList = new ArrayList<>();
                    cartonCodeList.addAll(Arrays.asList(existCartonCodeArr));
                    cartonCodeList.add(cartonCode);
                    String updateCartonCode = cartonCodeList.stream().collect(Collectors.joining(","));
                    kisMaterielExWarehouseDO.setCartonCode(updateCartonCode);
                }
                if (StringUtils.isBlank(existCartonCode)) {
                    kisMaterielExWarehouseDO.setCartonCode(cartonCode);
                }

                kisMaterielExWarehouseDO.setOperator(operator);
                kisMaterielExWarehouseDO.setUpdateTime(updateTime);

                // // 设置各个物料对应的箱码的数量为0
                // Integer codeNum = kisMaterielExWarehouseDO.getCodeNum();
                // String updateCartonCodes = kisMaterielExWarehouseDO.getCartonCode();
                // if (null != codeNum && StringUtils.isNotBlank(updateCartonCodes)) {
                //     String[] updateCartonCodeArr = updateCartonCodes.split(",");
                //     List<CartonCodeNumVO> cartonCodeNumVOS = new ArrayList<>();
                //     if (updateCartonCodeArr.length > 0) {
                //         for (String updateCartonCode : updateCartonCodeArr) {
                //             String type = kisMaterielExWarehouseDO.getType();
                //             CartonCodeNumVO cartonCodeNumVO = new CartonCodeNumVO();
                //             // cartonCodeNumVO.setOrderCode(orderCode);
                //             // cartonCodeNumVO.setType(kisMaterielExWarehouseDO.getType());
                //             // cartonCodeNumVO.setCode(code);
                //             cartonCodeNumVO.setId(kisMaterielExWarehouseDO.getId());
                //             cartonCodeNumVO.setCartonCode(updateCartonCode);
                //             cartonCodeNumVO.setNum(0);
                //             cartonCodeNumVOS.add(cartonCodeNumVO);
                //         }
                //         String cartonJson = JsonUtils.toJsonString(cartonCodeNumVOS);
                //         kisMaterielExWarehouseDO.setCartonJson(cartonJson);
                //     }
                // }

                kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
            }
        }
        return null;
    }

    @Override
    public String bindBoxCodeEdit(KisMaterielExWarehouseSaveReqVO createReqVO) {
        String orderCode = createReqVO.getOrderCode();
        String cartonCode = createReqVO.getCartonCode();
        String type = createReqVO.getType();
        String operator = createReqVO.getOperator();

        KisBatchCodeDO kisBatchCodeDO = kisBatchCodeMapper.selectById(cartonCode);
        if (null == kisBatchCodeDO) {
            throw new ServiceException(ERROR_STATUS, "箱码不存在,请重新扫码");
        }

        String[] cartonCodeArr = cartonCode.split("_");
        if (cartonCodeArr.length != 3) {
            throw new ServiceException(ERROR_STATUS, "箱码格式错误,请重新扫码");
        }
        String code = cartonCodeArr[0];

        // 根据生产订单和型号去查该物料出库单是否绑定了箱码,如果没绑定则绑定
        QueryWrapper<KisMaterielExWarehouseDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", orderCode);
        queryWrapper.eq("code", code);
        queryWrapper.eq("type", type);
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            LocalDateTime updateTime = LocalDateTime.now();
            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                String existCartonCode = kisMaterielExWarehouseDO.getCartonCode();
                if (StringUtils.isBlank(existCartonCode)) {
                    existCartonCode = "";
                }
                // 对数据库的箱码进行分割,如果匹配到前端传入的箱码,则不用修改.如果未匹配到前端传入的箱码,则将前端传入的箱码拼接到数据库的箱码
                String[] existCartonCodeArr = existCartonCode.split(",");
                if (StringUtils.isNotBlank(existCartonCode) && existCartonCodeArr.length > 0 && !Arrays.asList(existCartonCodeArr).contains(cartonCode)) {
                    List<String> cartonCodeList = new ArrayList<>();
                    cartonCodeList.addAll(Arrays.asList(existCartonCodeArr));
                    cartonCodeList.add(cartonCode);
                    String updateCartonCode = cartonCodeList.stream().collect(Collectors.joining(","));
                    kisMaterielExWarehouseDO.setCartonCode(updateCartonCode);
                }
                if (StringUtils.isBlank(existCartonCode)) {
                    kisMaterielExWarehouseDO.setCartonCode(cartonCode);
                }

                kisMaterielExWarehouseDO.setOperator(operator);
                kisMaterielExWarehouseDO.setUpdateTime(updateTime);

                kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
            }
        }
        return null;
    }

    @Override
    public String materiaPick(KisMaterielExWarehouseSaveReqVO createReqVO) {
        String orderCode = createReqVO.getOrderCode();
        String type = createReqVO.getType();
        String code = createReqVO.getCode();
        String racketModel = createReqVO.getRacketModel();
        String sheetNum = createReqVO.getSheetNum();
        String weight = createReqVO.getWeight();
        String cutSize = createReqVO.getCutSize();
        String knivesNum = createReqVO.getKnivesNum();
        String amount = createReqVO.getAmount();
        String materialsCut = createReqVO.getMaterialsCut();
        String addLayers = createReqVO.getAddLayers();
        // String materialCheck = createReqVO.getMaterialCheck();
        // String issuMaterials = createReqVO.getIssuMaterials();
        // String remark = createReqVO.getRemark();
        String materialStatus = createReqVO.getMaterialStatus();

        // 根据生产订单和型号去查该物料出库单是否绑定了箱码,如果没绑定则绑定
        QueryWrapper<KisMaterielExWarehouseDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", orderCode);
        queryWrapper.eq("type", type);
        queryWrapper.eq("code", code);
        String id = createReqVO.getId();
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            // LocalDate localDate = LocalDate.now();
            // LocalDateTime updateDate = localDate.atTime(0, 0, 0);
            LocalDateTime updateTime = LocalDateTime.now();
            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                kisMaterielExWarehouseDO.setUpdateTime(updateTime);
                kisMaterielExWarehouseDO.setRacketModel(racketModel);
                kisMaterielExWarehouseDO.setSheetNum(sheetNum);
                kisMaterielExWarehouseDO.setWeight(weight);
                kisMaterielExWarehouseDO.setCutSize(cutSize);
                kisMaterielExWarehouseDO.setKnivesNum(knivesNum);
                kisMaterielExWarehouseDO.setAmount(amount);
                kisMaterielExWarehouseDO.setMaterialsCut(materialsCut);
                kisMaterielExWarehouseDO.setAddLayers(addLayers);
                // kisMaterielExWarehouseDO.setMaterialCheck(materialCheck);
                // kisMaterielExWarehouseDO.setIssuMaterials(issuMaterials);
                // kisMaterielExWarehouseDO.setRemark(remark);
                kisMaterielExWarehouseDO.setMaterialStatus(MATERIAL_STATUS_2);
                kisMaterielExWarehouseDO.setCartonCode("");
                kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
            }
        }
        if (CollectionUtil.isEmpty(kisMaterielExWarehouseDOS)) {
            KisMaterielExWarehouseDO kisMaterielExWarehouseDO = BeanUtils.toBean(createReqVO, KisMaterielExWarehouseDO.class);
            // kisMaterielExWarehouseDO.setId(UuidUtil.getUuid());
            kisMaterielExWarehouseDO.setId(orderCode + "_" + type + "_" + code);
            kisMaterielExWarehouseDO.setRacketModel(racketModel);
            kisMaterielExWarehouseDO.setSheetNum(sheetNum);
            kisMaterielExWarehouseDO.setWeight(weight);
            kisMaterielExWarehouseDO.setCutSize(cutSize);
            kisMaterielExWarehouseDO.setKnivesNum(knivesNum);
            kisMaterielExWarehouseDO.setAmount(amount);
            kisMaterielExWarehouseDO.setMaterialsCut(materialsCut);
            kisMaterielExWarehouseDO.setAddLayers(addLayers);
            // kisMaterielExWarehouseDO.setMaterialCheck(materialCheck);
            // kisMaterielExWarehouseDO.setIssuMaterials(issuMaterials);
            // kisMaterielExWarehouseDO.setRemark(remark);
            kisMaterielExWarehouseDO.setMaterialStatus(MATERIAL_STATUS_2);
            kisMaterielExWarehouseDO.setCartonCode("");
            kisMaterielExWarehouseMapper.insert(kisMaterielExWarehouseDO);
            return kisMaterielExWarehouseDO.getId();
        }
        return id;
    }

    @Override
    public List<KisMaterielExWarehouseDO> selectMaterialByCartonCodes(Map<String, Object> params) {
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectMaterialByCartonCodes(params);
        return kisMaterielExWarehouseDOS;
    }

    @Override
    public Long countMaterialExWarehouseList(Map<String, Object> params) {
        Long count = kisMaterielExWarehouseMapper.countMaterialExWarehouseList(params);
        return count;
    }

    @Override
    public List<KisMaterialExWarehouseListVO> selectMaterialExWarehouseList(Map<String, Object> params) {
        List<KisMaterialExWarehouseListVO> kisMaterialExWarehouseListVOS = kisMaterielExWarehouseMapper.selectMaterialExWarehouseList(params);
        return kisMaterialExWarehouseListVOS;
    }

    @Override
    public PageResult<KisMaterielExWarehouseDO> detailByExCode(KisMaterielExWarehousePageReqVO pageReqVO) {
        pageReqVO.setSubmitStatus("1");
        PageResult<KisMaterielExWarehouseDO> result = kisMaterielExWarehouseMapper.detailByExCode(pageReqVO);
        if (CollectionUtil.isEmpty(result.getList())) {
            KisMaterielExWarehouseRecyclePageReqVO kisMaterielExWarehouseRecyclePageReqVO = new KisMaterielExWarehouseRecyclePageReqVO();
            kisMaterielExWarehouseRecyclePageReqVO.setExCode(pageReqVO.getExCode());
            PageResult<KisMaterielExWarehouseRecycleDO> kisMaterielExWarehouseRecycleDOPageResult = kisMaterielExWarehouseRecycleMapper.detailByExCode(kisMaterielExWarehouseRecyclePageReqVO);
            List<KisMaterielExWarehouseRecycleDO> list = kisMaterielExWarehouseRecycleDOPageResult.getList();
            if (CollectionUtil.isNotEmpty(list)) {
                List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = new ArrayList<>();
                for (KisMaterielExWarehouseRecycleDO kisMaterielExWarehouseRecycleDO : list) {
                    KisMaterielExWarehouseDO kisMaterielExWarehouseDO = BeanUtils.toBean(kisMaterielExWarehouseRecycleDO, KisMaterielExWarehouseDO.class);
                    kisMaterielExWarehouseDO.setId(kisMaterielExWarehouseRecycleDO.getExWarehouseId());
                    kisMaterielExWarehouseDOS.add(kisMaterielExWarehouseDO);
                }
                result.setList(kisMaterielExWarehouseDOS);
            }
        }
        return result;
    }

    @Override
    public List<CartonCodeDetailNumVO> queryMultiCartonCode(KisMaterielExWarehouseSaveReqVO createReqVO) {
        String orderCode = createReqVO.getOrderCode();
        if (StringUtils.isBlank(orderCode)) {
            return new ArrayList<>();
        }

        List<CartonCodeDetailNumVO> result = new ArrayList<>();
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectList("order_code", orderCode);
        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            // 查找编号最大的出库单,即为当前出库单
            String lastExCode = kisMaterielExWarehouseDOS.stream()
                    .sorted((s2, s1) -> s1.getExCode().compareTo(s2.getExCode()))
                    .collect(Collectors.toList())
                    .get(0)
                    .getExCode();

            // 选出当前出库单
            List<KisMaterielExWarehouseDO> multiCartonCodeInfoList = kisMaterielExWarehouseDOS.stream()
                    .filter(c -> StringUtils.equals(c.getExCode(), lastExCode))
                    .filter(c -> c.getCartonCode().contains(","))
                    .collect(Collectors.toList());

            if (CollectionUtil.isNotEmpty(multiCartonCodeInfoList)) {
                for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : multiCartonCodeInfoList) {
                    String id = kisMaterielExWarehouseDO.getId();
                    String type = kisMaterielExWarehouseDO.getType();
                    String code = kisMaterielExWarehouseDO.getCode();
                    String cartonCode = kisMaterielExWarehouseDO.getCartonCode();
                    String cartonJson = kisMaterielExWarehouseDO.getCartonJson();
                    List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS = JSONArray.parseArray(cartonJson, CartonCodeDetailNumVO.class);
                    // 如果cartonJson不为空,则将cartonJson中的id设置成当前物料出库单的id
                    if (CollectionUtil.isNotEmpty(cartonCodeDetailNumVOS)) {
                        for (CartonCodeDetailNumVO cartonCodeDetailNumVO : cartonCodeDetailNumVOS) {
                            cartonCodeDetailNumVO.setId(id);
                            cartonCodeDetailNumVO.setOrderCode(orderCode);
                            cartonCodeDetailNumVO.setType(type);
                            cartonCodeDetailNumVO.setCode(code);
                            cartonCodeDetailNumVO.setExCode(lastExCode);
                        }
                        result.addAll(cartonCodeDetailNumVOS);
                    }
                    // 如果cartonJson为空,则用cartonCode的数据,且数量设置成0
                    if (CollectionUtil.isEmpty(cartonCodeDetailNumVOS) && StringUtils.isNotBlank(cartonCode)) {
                        String[] multiCartonCodeArr = cartonCode.split(",");
                        List<String> multiCartonCodeList = Arrays.asList(multiCartonCodeArr);
                        List<CartonCodeDetailNumVO> cartonCodeNumList = new ArrayList<>();
                        for (String multiCartonCode : multiCartonCodeList) {
                            CartonCodeDetailNumVO cartonCodeDetailNumVO = new CartonCodeDetailNumVO();
                            cartonCodeDetailNumVO.setId(id);
                            cartonCodeDetailNumVO.setOrderCode(orderCode);
                            cartonCodeDetailNumVO.setType(type);
                            cartonCodeDetailNumVO.setCode(code);
                            cartonCodeDetailNumVO.setCartonCode(multiCartonCode);
                            cartonCodeDetailNumVO.setExCode(lastExCode);
                            cartonCodeDetailNumVO.setNum(0);
                            cartonCodeNumList.add(cartonCodeDetailNumVO);
                        }
                        result.addAll(cartonCodeNumList);
                    }
                }
            }
        }

        return result;
    }

    @Override
    public List<CartonCodeDetailNumVO> updateMultiCartonCode(List<CartonCodeDetailNumVO> reqVO) {
        if (CollectionUtil.isEmpty(reqVO)) {
            return null;
        }

        List<String> ids = reqVO.stream()
                .map(c -> c.getId())
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(ids)) {
            // 任意取一个id,获得其订单号
            KisMaterielExWarehouseDO warehouseDO = kisMaterielExWarehouseMapper.selectById(ids.get(0));
            String orderCode = warehouseDO.getOrderCode();

            // 根据订单号获得订单详情的每种产品总数,即该订单的内码总数,将订单的型号与对应的内码数量放在集合中,后面会用到
            // OrderDO orderDO = orderMapper.selectOne("id", orderCode);
            Map<String, Object> typeNumMap = new HashMap<>();
            Map<String, Object> typeNumParams = new HashMap<>();
            typeNumParams.put("orderCode", orderCode);
            List<OrderFlexNumVO> orderFlexNumVOS = orderMapper.selectTypeNumByOrderCode(typeNumParams);
            // List<OrderDetailDO> orderDetailDOS = orderDetailMapper.selectList("order_code", orderCode);
            if (CollectionUtil.isNotEmpty(orderFlexNumVOS)) {
                for (OrderFlexNumVO orderDetailDO : orderFlexNumVOS) {
                    String type = orderDetailDO.getType();
                    Integer totalNum = orderDetailDO.getNum().intValue();

                    // int totalNum = orderDO.getTotalNum().intValue();
                    int remainNum = totalNum;
                    // 再根据当前订单号去历史出库里面查已经出库数量
                    Map<String, Object> exHisParams = new HashMap<>();
                    exHisParams.put("orderCode", orderCode);
                    exHisParams.put("type", type);
                    Integer exNum = kisMaterielExWarehouseHistoryMapper.selectExNumByOrderCodeAndType(exHisParams);
                    if (null != exNum) {
                        remainNum = totalNum - exNum;
                    }

                    typeNumMap.put(orderCode + "_" + type, remainNum);
                }
            }

            Map<String, Object> idNumMap = new HashMap<>();
            // List<Integer> numList = new ArrayList<>();
            for (String id : ids) {
                List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS = new ArrayList<>();
                for (CartonCodeDetailNumVO cartonCodeDetailNumVO : reqVO) {
                    if (StringUtils.equals(id, cartonCodeDetailNumVO.getId())) {
                        cartonCodeDetailNumVOS.add(cartonCodeDetailNumVO);
                    }
                }

                // 计算每个物料的箱码对应的数量合计值
                if (CollectionUtil.isNotEmpty(cartonCodeDetailNumVOS)) {
                    IntSummaryStatistics intSummaryStatistics = cartonCodeDetailNumVOS.stream()
                            .mapToInt(CartonCodeDetailNumVO::getNum).summaryStatistics();
                    int sum = (int) intSummaryStatistics.getSum();
                    // numList.add(sum);
                    idNumMap.put(id, sum);
                }

            }

            // 统计订单各类型对应的物料的内码数量
            List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS1 = new ArrayList<>();
            for (Map.Entry<String, Object> stringObjectEntry : idNumMap.entrySet()) {
                String key = stringObjectEntry.getKey();
                Integer value = (Integer) stringObjectEntry.getValue();
                CartonCodeDetailNumVO cartonCodeDetailNumVO = new CartonCodeDetailNumVO();
                String[] idArr = key.split("_");
                cartonCodeDetailNumVO.setId(key);
                cartonCodeDetailNumVO.setOrderCode(idArr[0]);
                cartonCodeDetailNumVO.setType(idArr[1]);
                cartonCodeDetailNumVO.setNum(value);
                cartonCodeDetailNumVOS1.add(cartonCodeDetailNumVO);
            }

            List<String> types = reqVO.stream()
                    .map(c -> c.getOrderCode() + "_" + c.getType())
                    .distinct()
                    .collect(Collectors.toList());


            // 统计订单各类型的内码数量
            List<CartonCodeTotalNumVO> cartonCodeTotalNumVOS = new ArrayList<>();
            for (String type : types) {
                String[] typeArr = type.split("_");
                CartonCodeTotalNumVO cartonCodeTotalNumVO = new CartonCodeTotalNumVO();
                cartonCodeTotalNumVO.setOrderCode(typeArr[0]);
                cartonCodeTotalNumVO.setType(typeArr[1]);
                List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS2 = new ArrayList<>();
                for (CartonCodeDetailNumVO cartonCodeDetailNumVO : cartonCodeDetailNumVOS1) {
                    if (StringUtils.equals(type, cartonCodeDetailNumVO.getOrderCode() + "_" + cartonCodeDetailNumVO.getType())) {
                        cartonCodeDetailNumVOS2.add(cartonCodeDetailNumVO);
                    }
                }
                cartonCodeTotalNumVO.setDetailNumList(cartonCodeDetailNumVOS2);
                cartonCodeTotalNumVOS.add(cartonCodeTotalNumVO);
            }

            for (CartonCodeTotalNumVO cartonCodeTotalNumVO : cartonCodeTotalNumVOS) {
                String type = cartonCodeTotalNumVO.getType();
                List<CartonCodeDetailNumVO> detailNumList = cartonCodeTotalNumVO.getDetailNumList();
                IntSummaryStatistics intSummaryStatistics = detailNumList.stream()
                        .mapToInt(c -> c.getNum()).summaryStatistics();

                int min = intSummaryStatistics.getMin();
                int max = intSummaryStatistics.getMax();
                if (min != max) {
                    throw new ServiceException(ERROR_STATUS, "型号" + type + "的混批箱码生成的内码总数量不一致");
                }
                // 如果累计混合值大于当前订单的未出库总数,则提示
                Integer remainNum = (Integer) typeNumMap.get(orderCode + "_" + type);
                if (max > remainNum) {
                    throw new ServiceException(ERROR_STATUS, "型号" + type + "的内码数量最大不能超过" + remainNum);
                }
                if (min == 0) {
                    throw new ServiceException(ERROR_STATUS, "型号" + type + "的混批箱码生成的内码总数量不能为0");
                }
                cartonCodeTotalNumVO.setNum(min);
            }


            for (String id : ids) {
                List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS = new ArrayList<>();
                for (CartonCodeDetailNumVO cartonCodeDetailNumVO : reqVO) {
                    if (StringUtils.equals(id, cartonCodeDetailNumVO.getId())) {
                        cartonCodeDetailNumVOS.add(cartonCodeDetailNumVO);
                    }
                }

                String cartonJson = JsonUtils.toJsonString(cartonCodeDetailNumVOS);
                if (CollectionUtil.isNotEmpty(cartonCodeDetailNumVOS)) {
                    KisMaterielExWarehouseDO kisMaterielExWarehouseDO = new KisMaterielExWarehouseDO();
                    kisMaterielExWarehouseDO.setId(id);
                    kisMaterielExWarehouseDO.setCartonJson(cartonJson);
                    kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
                }
            }

            // 根据订单各类型找出carton_code只有一个的
            for (CartonCodeTotalNumVO cartonCodeTotalNumVO : cartonCodeTotalNumVOS) {
                String type = cartonCodeTotalNumVO.getType();
                Integer num = cartonCodeTotalNumVO.getNum();
                Map<String, Object> param = new HashMap<>();
                param.put("orderCode", orderCode);
                param.put("type", type);
                List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectSingleCartonByOrderCodeAndType(param);
                if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
                    for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                        String id = kisMaterielExWarehouseDO.getId();
                        String code = kisMaterielExWarehouseDO.getCode();
                        String cartonCode = kisMaterielExWarehouseDO.getCartonCode();
                        String exCode = kisMaterielExWarehouseDO.getExCode();
                        List<CartonCodeDetailNumVO> cartonCodeDetailNumVOS = new ArrayList<>();
                        CartonCodeDetailNumVO cartonCodeDetailNumVO = new CartonCodeDetailNumVO();
                        cartonCodeDetailNumVO.setId(id);
                        cartonCodeDetailNumVO.setOrderCode(orderCode);
                        cartonCodeDetailNumVO.setType(type);
                        cartonCodeDetailNumVO.setCode(code);
                        cartonCodeDetailNumVO.setCartonCode(cartonCode);
                        cartonCodeDetailNumVO.setExCode(exCode);
                        cartonCodeDetailNumVO.setNum(num);
                        cartonCodeDetailNumVOS.add(cartonCodeDetailNumVO);
                        String cartonJson = JsonUtils.toJsonString(cartonCodeDetailNumVOS);
                        kisMaterielExWarehouseDO.setCartonJson(cartonJson);
                        kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
                    }
                }

            }


        }

        return null;
    }


    @Override
    public List<CartonCodeDetailNumVO> bindBoxCodeNumUpdate(List<CartonCodeDetailNumVO> reqVO) {
        if (CollectionUtil.isEmpty(reqVO)) {
            return null;
        }

        Map<String, List<CartonCodeDetailNumVO>> warehouseMap = new HashMap<>();

        for (CartonCodeDetailNumVO itemVO : reqVO) {
            CartonCodeDetailNumVO cartonCodeDetailNumVO = new CartonCodeDetailNumVO();
            cartonCodeDetailNumVO.setId(itemVO.getId());
            cartonCodeDetailNumVO.setOrderCode(itemVO.getOrderCode());
            cartonCodeDetailNumVO.setType(itemVO.getType());
            cartonCodeDetailNumVO.setCode(itemVO.getCode());
            cartonCodeDetailNumVO.setCartonCode(itemVO.getCartonCode());
            cartonCodeDetailNumVO.setExCode(itemVO.getExCode());

            if (ObjectUtils.isEmpty(itemVO.getNum()) || itemVO.getNum().intValue() == 0) {
                KisMaterielExWarehouseDO kisMaterielExWarehouseDO = kisMaterielExWarehouseMapper.selectById(itemVO.getId());
                cartonCodeDetailNumVO.setNum(kisMaterielExWarehouseDO.getCodeNum());
            } else {
                cartonCodeDetailNumVO.setNum(itemVO.getNum());
            }

            List<CartonCodeDetailNumVO> list = null;
            if (ObjectUtils.isEmpty(warehouseMap.get(itemVO.getId()))) {
                list = new ArrayList<>();
                list.add(cartonCodeDetailNumVO);
            } else {
                list = warehouseMap.get(itemVO.getId());
                list.add(cartonCodeDetailNumVO);
            }
            warehouseMap.put(itemVO.getId(), list);
        }


        CartonCodeDetailNumVO vo = reqVO.get(0);
        String orderCode = vo.getOrderCode();
        String type = vo.getType();

        QueryWrapper<KisMaterielExWarehouseDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", orderCode);
        queryWrapper.eq("type", type);
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOList = kisMaterielExWarehouseMapper.selectList(queryWrapper);
        for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOList) {
            List<CartonCodeDetailNumVO> list = warehouseMap.get(kisMaterielExWarehouseDO.getId());
            int total = list.stream().mapToInt(c -> c.getNum()).sum();
            if (total != kisMaterielExWarehouseDO.getCodeNum()) {
                throw new ServiceException(ERROR_STATUS, "箱码" + kisMaterielExWarehouseDO.getCode() + "的明细内码数量不一致");
            }
        }

        warehouseMap.keySet().forEach(id -> {
            List<CartonCodeDetailNumVO> list = warehouseMap.get(id);
            String cartonJson = JsonUtils.toJsonString(list);
            KisMaterielExWarehouseDO kisMaterielExWarehouseDO = new KisMaterielExWarehouseDO();
            kisMaterielExWarehouseDO.setId(id);
            kisMaterielExWarehouseDO.setCartonJson(cartonJson);
            kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
        });

        return null;
    }

    @Override
    public Integer selectUncheckMaterialByOrderCode(Map<String, Object> params) {
        Integer count = kisMaterielExWarehouseMapper.selectUncheckMaterialByOrderCode(params);
        return count;
    }

    @Override
    public List<KisMaterielExWarehouseDO> selectTypeByOrderCode(Map<String, Object> params) {
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectTypeByOrderCode(params);
        return kisMaterielExWarehouseDOS;
    }

    @Override
    public List<KisMaterielExWarehouseDO> selectLastExCodeByOrderCode(Map<String, Object> params) {
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectLastExCodeByOrderCode(params);
        return kisMaterielExWarehouseDOS;
    }

    @Override
    public List<KisMaterialExWarehouseListVO> selectExCodeByOrderCode(Map<String, Object> params) {
        List<KisMaterialExWarehouseListVO> kisMaterielExWarehouseDOS = kisMaterielExWarehouseMapper.selectExCodeByOrderCode(params);
        return kisMaterielExWarehouseDOS;
    }

    @Override
    public Long countExCodeByOrderCode(Map<String, Object> params) {
        Long count = kisMaterielExWarehouseMapper.countExCodeByOrderCode(params);
        return count;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean submitProductCollect(List<MaterialProductCollectVO> createReqVOList) {

        if (CollectionUtil.isEmpty(createReqVOList)) {
            throw new ServiceException(new ErrorCode(ERROR_STATUS, "提交数据错误。"));
        }

        String orderCode = createReqVOList.get(0).getOrderCode();
        QueryWrapper<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOQueryWrapper = new QueryWrapper<>();
        kisMaterielExWarehouseDOQueryWrapper.eq("order_code", orderCode);
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOList = kisMaterielExWarehouseMapper.selectList(kisMaterielExWarehouseDOQueryWrapper);
        if (null != kisMaterielExWarehouseDOList && kisMaterielExWarehouseDOList.size() > 0) {
            boolean flag = false;
            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOList) {
                String materialStatus = kisMaterielExWarehouseDO.getMaterialStatus();
                if (StringUtils.equals(materialStatus, MATERIAL_STATUS_1)) {
                    flag = true;
                } else {
                    flag = false;
                    break;
                }
            }

            if (flag) {
                throw new ServiceException(new ErrorCode(ERROR_STATUS, "该订单数据已审核，无法重复领料。"));
            }
        }

        kisMaterielExWarehouseDOQueryWrapper = new QueryWrapper<>();
        kisMaterielExWarehouseDOQueryWrapper.eq("order_code", orderCode);
        kisMaterielExWarehouseDOQueryWrapper.eq("material_status", MATERIAL_STATUS_0);
        Long count = kisMaterielExWarehouseMapper.selectCount(kisMaterielExWarehouseDOQueryWrapper);

        boolean rejectFlag = false;

        if (count > 0) {
            rejectFlag = true;
            for (MaterialProductCollectVO createReqVO : createReqVOList) {
                kisMaterielExWarehouseDOQueryWrapper = new QueryWrapper<>();
                kisMaterielExWarehouseDOQueryWrapper.eq("order_code", orderCode);
                kisMaterielExWarehouseDOQueryWrapper.eq("type", createReqVO.getType());
                kisMaterielExWarehouseDOQueryWrapper.eq("code", createReqVO.getMaterialCode());
                kisMaterielExWarehouseDOQueryWrapper.eq("material_status", MATERIAL_STATUS_0);
                count = kisMaterielExWarehouseMapper.selectCount(kisMaterielExWarehouseDOQueryWrapper);
                if (count == 0) {
                    throw new ServiceException(new ErrorCode(ERROR_STATUS, "输入的规格或织板编码错误"));
                }
            }
        }

        List<DispatchListDO> dispatchTypeList = dispatchListMapper.selectList(DispatchListDO::getTicketNumber, orderCode);
        List<String> modelKpList = dispatchTypeList.stream().map(dispatchListDO -> dispatchListDO.getModelKp()).collect(Collectors.toList());

        List<String> typeList = createReqVOList.stream().map(item -> item.getType()).collect(Collectors.toList());

        for (String modelKp : modelKpList) {
            if (!typeList.contains(modelKp)) {
                throw new ServiceException(new ErrorCode(ERROR_STATUS, "型号" + modelKp + "数据不存在!"));
            }
        }

        for (MaterialProductCollectVO createReqVO : createReqVOList) {

            String type = createReqVO.getType();
            if (!rejectFlag) {
                if (!modelKpList.contains(type)) {
                    throw new ServiceException(new ErrorCode(ERROR_STATUS, "型号" + type + "数据不存在!"));
                }
            }

            List<CartonCodeVO> cartonCodeVOList = createReqVO.getCartonCodeList();

            if (cartonCodeVOList == null || cartonCodeVOList.size() == 0) {
                throw new ServiceException(new ErrorCode(ERROR_STATUS, "型号" + type + "的件数有误"));
            }

            orderCode = createReqVO.getOrderCode();
            QueryWrapper<DispatchListDO> dispatchListDOQueryWrapper = new QueryWrapper<>();
            dispatchListDOQueryWrapper.eq("ticket_number", orderCode);
            dispatchListDOQueryWrapper.eq("model_kp", createReqVO.getType());

            List<DispatchListDO> dispatchListDOList = dispatchListMapper.selectList(dispatchListDOQueryWrapper);
            int quantityTotal = dispatchListDOList.stream()
                    .map(dispatchListDO -> dispatchListDO.getQuantity())
                    .collect(Collectors.toList())
                    .stream()
                    .mapToInt(Integer::intValue)
                    .sum();

            int meterialTotalNum = 0;
            String cartonCode;

            if (cartonCodeVOList.size() > 1) {
                meterialTotalNum = cartonCodeVOList.stream().mapToInt(c -> Integer.parseInt(c.getMaterialNum())).sum();
                List<String> cartonIdList = cartonCodeVOList.stream().map(c -> c.getCartonId()).collect(Collectors.toList());
                cartonCode = String.join(",", cartonIdList);
            } else {
                meterialTotalNum = quantityTotal;
                cartonCode = cartonCodeVOList.get(0).getCartonId();
            }

            if (quantityTotal != meterialTotalNum) {
                throw new ServiceException(new ErrorCode(ERROR_STATUS, String.format("规格[%s]和物料号[%s]输入的总件数有误", type, createReqVO.getMaterialCode())));
            }

            if (quantityTotal == 0) {
                throw new ServiceException(new ErrorCode(ERROR_STATUS, "型号" + type + "的件数有误"));
            }

            KisMaterielExWarehouseDO kisMaterielExWarehouseDO = new KisMaterielExWarehouseDO();
            String id = orderCode + "_" + type + "_" + createReqVO.getMaterialCode() + "_000000001";
            kisMaterielExWarehouseDO.setId(id);
            String exCode = "CK" + orderCode + "_000000001";
            kisMaterielExWarehouseDO.setExCode(exCode);
            kisMaterielExWarehouseDO.setOrderCode(orderCode);
            kisMaterielExWarehouseDO.setType(type);
            kisMaterielExWarehouseDO.setCode(createReqVO.getMaterialCode());
            kisMaterielExWarehouseDO.setCodeNum(quantityTotal);
            kisMaterielExWarehouseDO.setCartonCode(cartonCode);
            kisMaterielExWarehouseDO.setMaterialStatus(MATERIAL_STATUS_2);
            kisMaterielExWarehouseDO.setSubmitStatus(SUBMIT_STATUS_1);
            kisMaterielExWarehouseDO.setDataSource(2);

            JSONArray cartonCodeJsonArray = new JSONArray();

            for (CartonCodeVO cartonCodeVO : cartonCodeVOList) {
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("orderCode", orderCode);
                jsonObject.put("type", type);
                jsonObject.put("code", createReqVO.getMaterialCode());
                jsonObject.put("exCode", createReqVO.getMaterialCode());
                jsonObject.put("id", id);
                if (cartonCodeVOList.size() > 1) {
                    jsonObject.put("num", cartonCodeVO.getMaterialNum());
                } else {
                    jsonObject.put("num", quantityTotal);
                }
                jsonObject.put("cartonCode", cartonCodeVO.getCartonId());
                cartonCodeJsonArray.add(jsonObject);
            }

            kisMaterielExWarehouseDO.setCartonJson(cartonCodeJsonArray.toJSONString());

            KisMaterielExWarehouseDO oldDO = kisMaterielExWarehouseMapper.selectById(id);
            if (ObjectUtils.isEmpty(oldDO)) {
                kisMaterielExWarehouseMapper.insert(kisMaterielExWarehouseDO);
            } else {
                kisMaterielExWarehouseMapper.updateById(kisMaterielExWarehouseDO);
            }

            DispatchListDO dispatchListDO = new DispatchListDO();
            dispatchListDO.setStatus(projectDefine.ORDER_STATUS.ORDER_STATUS_1);
            dispatchListMapper.update(dispatchListDO, new QueryWrapper<DispatchListDO>().eq("ticket_number", orderCode));

        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createInternalCodeByOrderCode(PreparationVO reqVO) {
        String orderCode = reqVO.getOrderCode();

        if (StringUtils.isBlank(orderCode)) {
            Assert.notNull(null,"请输入生产订单");
        }

        Object typeObj = reqVO.getType();
        String type = null;
        if (null != typeObj) {
            type = typeObj.toString();
        }

        Map<String, Object> param = new HashMap<>();
        param.put("orderCode", orderCode);
        param.put("type", type);

        // 根据订单编号查询最近的物料单,如果物料单中有物料审核状态未通过,则提示
        List<KisMaterielExWarehouseDO> lastExCodeList = selectLastExCodeByOrderCode(param);
        if (CollectionUtil.isNotEmpty(lastExCodeList)) {
            List<KisMaterielExWarehouseDO> uncheckList = lastExCodeList.stream()
                    .filter(c -> !StringUtils.equals(MATERIAL_STATUS_1, c.getMaterialStatus()))
                    .collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(uncheckList)) {
                throw new ServiceException(ERROR_STATUS, "当前物料单中有物料审核状态未通过");
            }
        }

        QueryWrapper<KisMaterielExWarehouseHistoryDO> kisMaterielExWarehouseHistoryDOQueryWrapper = new QueryWrapper<>();
        kisMaterielExWarehouseHistoryDOQueryWrapper.eq("order_code", orderCode);
        kisMaterielExWarehouseHistoryDOQueryWrapper.eq(!StringUtils.isEmpty(type), "type", type);
        Long count = kisMaterielExWarehouseHistoryMapper.selectCount(kisMaterielExWarehouseHistoryDOQueryWrapper);
        if (count > 0) {
            throw new ServiceException(ERROR_STATUS, "当前订单已出库,请勿重复出库");
        }


        // 根据订单编号查询各型号
        List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS = selectTypeByOrderCode(param);

        if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS)) {
            LocalDateTime now = LocalDateTime.now();

            List<CompletableFuture<Boolean>> completableFutureList = new ArrayList<>();

            for (KisMaterielExWarehouseDO kisMaterielExWarehouseDO : kisMaterielExWarehouseDOS) {
                String exCode = kisMaterielExWarehouseDO.getExCode();
                String typeStr = kisMaterielExWarehouseDO.getType();
                QueryWrapper<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOQueryWrapper = new QueryWrapper<>();
                kisMaterielExWarehouseDOQueryWrapper.eq("ex_code", exCode);
                kisMaterielExWarehouseDOQueryWrapper.eq("type", typeStr);
                List<KisMaterielExWarehouseDO> kisMaterielExWarehouseDOS1 = kisMaterielExWarehouseMapper.selectList(kisMaterielExWarehouseDOQueryWrapper);
                if (CollectionUtil.isNotEmpty(kisMaterielExWarehouseDOS1)) {
                    // 取第一个元素中的carton_json
                    KisMaterielExWarehouseDO kisMaterielExWarehouseDO1 = kisMaterielExWarehouseDOS1.get(0);
                    String cartonCodes = kisMaterielExWarehouseDO1.getCartonCode();
                    String cartonJson = kisMaterielExWarehouseDO1.getCartonJson();
                    if (StringUtils.isNotBlank(cartonJson)) {
                        List<CartonCodeDetailNumVO> orderFlexNumVOS = JSONArray.parseArray(cartonJson, CartonCodeDetailNumVO.class);
                        if (CollectionUtil.isNotEmpty(orderFlexNumVOS)) {
                            Integer startNum = 0;
                            Map<String, Object> exNumParam = new HashMap<>();
                            exNumParam.put("orderCode", orderCode);
                            exNumParam.put("type", typeStr);
                            Integer exNum = kisMaterielExWarehouseHistoryMapper.selectExNumByExCode(exNumParam);
                            if (null != exNum) {
                                startNum = exNum;
                            }
                            List<InternalCodeDO> internalCodeDOS = new ArrayList<>();
                            for (CartonCodeDetailNumVO orderFlexNumVO : orderFlexNumVOS) {
                                Integer num = orderFlexNumVO.getNum();
                                String cartonCode = orderFlexNumVO.getCartonCode();
                                String[] cartonCodeArr = cartonCode.split("_");
                                String batchNumber = cartonCodeArr[2];
                                String code = orderFlexNumVO.getCode();

                                KisMaterielExWarehouseDO existKisMaterielExWarehouseDO = kisMaterielExWarehouseMapper.selectById(orderFlexNumVO.getId());
                                Integer dataSource = existKisMaterielExWarehouseDO.getDataSource();

                                for (Integer i = startNum + 1; i < startNum + num + 1; i++) {
                                    InternalCodeDO internalCodeDO = new InternalCodeDO();
                                    internalCodeDO.setExCode(exCode);
                                    internalCodeDO.setOrderCode(orderCode);
                                    internalCodeDO.setType(typeStr);
                                    internalCodeDO.setBatchNumber(batchNumber);
                                    internalCodeDO.setMaterialCode(code);
                                    internalCodeDO.setCartonCodes(cartonCodes);
                                    String serialNumber = SERIAL_NUMBER_INIT + i;
                                    String batchCheckNumber = serialNumber.substring(serialNumber.length() - (SERIAL_NUMBER_INIT.length() + 1));
                                    internalCodeDO.setBatchCheckNumber(batchCheckNumber);
                                    internalCodeDO.setId(orderCode + "_" + typeStr + "_" + batchCheckNumber);
                                    internalCodeDO.setName("");
                                    internalCodeDO.setOperatingTime(now);
                                    internalCodeDO.setDataSource(dataSource);
                                    internalCodeDOS.add(internalCodeDO);
                                }
                                startNum = startNum + num;
                            }

                            //后面由于分批更新订单part_id须考虑循环的执行问题，这里一次更新完成
                            List<OrderDetailDO> orderDetailDOS = orderDetailMapper.selectList(new QueryWrapper<OrderDetailDO>().eq("order_code", orderCode).eq(!StringUtils.isEmpty(type), "SUBSTR(flex,1,6)", type));
                            List<InternalCodeDO> internalCodeDOS_test = new ArrayList<>(internalCodeDOS);
                            if(orderDetailDOS != null && orderDetailDOS.size() > 0){
                                int list_internalCodeDOS= 0;
                                for (int i=0 ; i<orderDetailDOS.size(); i++) {
                                    int numDetail = orderDetailDOS.get(i).getNum().intValue();
                                    String orderDetailPritId =  orderDetailDOS.get(i).getPartId();
                                    for(int k=0; k<numDetail; k++) {
                                        internalCodeDOS_test.get(list_internalCodeDOS).setOrderDetailId(orderCode+"_"+orderDetailPritId);
                                        list_internalCodeDOS++;
                                    }
                                }
                            }else{
                                List<DispatchListDO> dispatchListDOList = dispatchListMapper.selectList(new QueryWrapper<DispatchListDO>().eq("ticket_number", orderCode).eq(!StringUtils.isEmpty(type), "flex", type));
                                if(null != dispatchListDOList && dispatchListDOList.size() > 0){
                                    for(DispatchListDO dispatchListDO : dispatchListDOList){
                                        String modelKp = dispatchListDO.getModelKp();
                                        int cnt = dispatchListDO.getQuantity();

                                        int index = 0;

                                        for(InternalCodeDO internalCodeDO : internalCodeDOS){
                                            if(internalCodeDO.getType().equals(modelKp) && internalCodeDO.getOrderDetailId() == null){
                                                if(index >= cnt){
                                                    break;
                                                }
                                                internalCodeDO.setOrderDetailId(dispatchListDO.getTicketNumber() + "_" + dispatchListDO.getId());
                                                index = index + 1;
                                            }
                                        }
                                    }
                                }
                            }



                            // 同时在出库历史中也写入对应的数量
                            IntSummaryStatistics intSummaryStatistics = orderFlexNumVOS.stream().mapToInt(c -> c.getNum()).summaryStatistics();
                            long sum = intSummaryStatistics.getSum();
                            KisMaterielExWarehouseHistoryDO kisMaterielExWarehouseHistoryDO = new KisMaterielExWarehouseHistoryDO();
                            kisMaterielExWarehouseHistoryDO.setId("HIS" + exCode + "_" + typeStr);
                            kisMaterielExWarehouseHistoryDO.setType(typeStr);
                            kisMaterielExWarehouseHistoryDO.setExCode(exCode);
                            kisMaterielExWarehouseHistoryDO.setOrderCode(orderCode);
                            kisMaterielExWarehouseHistoryDO.setExTime(now);
                            kisMaterielExWarehouseHistoryDO.setExNum((int) sum);
                            String nickname = SecurityFrameworkUtils.getLoginUserNickname();
                            kisMaterielExWarehouseHistoryDO.setOperator(nickname);

                            KisMaterielExWarehouseHistoryDO existsKisMaterielExWarehouseHistoryDO = kisMaterielExWarehouseHistoryMapper.selectOne("id", kisMaterielExWarehouseHistoryDO.getId());
                            if (null!=existsKisMaterielExWarehouseHistoryDO) {
                                throw new ServiceException(ERROR_STATUS, "当前领料单已出库,请勿重复出库");
                            }

                            completableFutureList.add(CompletableFuture.supplyAsync(() -> {
                                kisMaterielExWarehouseHistoryMapper.insert(kisMaterielExWarehouseHistoryDO);
                                internalCodeService.batchSaveRecord(internalCodeDOS);
                                checkWorkstationPlanCount(internalCodeDOS);
                                return true;
                            }));
                        }
                    }
                }

                CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[0])).join();

                // 检查所有结果
                for (CompletableFuture<Boolean> future : completableFutureList) {
                    try{
                        Boolean result = future.get();
                        if (result == null || !result) {
                            throw new RuntimeException("其中一个任务执行失败!");
                        }
                    }catch (Exception e){
                        throw new RuntimeException(e);
                    }
                }

            }
        }
    }

    private void checkWorkstationPlanCount(List<InternalCodeDO> internalCodeDOList) {

        List<String> internalCodeIdList = internalCodeDOList.stream().map(internalCodeDO -> internalCodeDO.getId()).collect(Collectors.toList());
        List<WorkstationDO> workstationDOList = workstationMapper.selectList();

        Long insertCount = internalWorkstationPlanMapper.selectCount(new QueryWrapper<InternalWorkstationPlanDO>().in("internal_code", internalCodeIdList));

        Integer tempWorkstationPlanCnt = internalCodeIdList.size() * workstationDOList.size();

        if(insertCount.intValue() != tempWorkstationPlanCnt.intValue()){
            throw new ServiceException(ERROR_STATUS, "工位计划数量错误!");
        }

    }
}